// Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use anyhow::Context;
use clap::Parser;

use crate::{build::BuildContext, commands::{resolve_stats, split_stat_specs, BuildGraphArgs}, deploy::uninstall_pkgs, FerriumCommand};

#[derive(Debug, Parser)]
pub struct UninstallCommand {
    /// Specify the toolchain to use
    #[arg(long)]
    toolchain: Option<String>,
    /// Pkg spec strings, pkg hash spec strings, or specs config paths
    specs: Vec<String>,
    /// Whether to remove dependant pkgs
    #[arg(short, long, default_value_t = true)]
    recursive: bool,
    /// Force remove pkgs even if they are deployed
    #[arg(short, long)]
    force_deployed: bool,
}

impl FerriumCommand for UninstallCommand {
    async fn run(self, _multi_progress: indicatif::MultiProgress) -> anyhow::Result<()> {
        let (pkg_specs, stat_specs) = split_stat_specs(self.specs);

        let (mut build_dep_graph, _, _) = BuildGraphArgs {
            specs: pkg_specs,
            toolchain: self.toolchain,
        }.build_graph().await?;
        let sorted_ids = build_dep_graph.verify(true)
            .context("failed to resolve specs")?;
        
        let hashes = BuildContext::spec_hashes(&build_dep_graph, &sorted_ids).await?;
        let spec_strings = BuildContext::prepare_spec_strings(&hashes, &build_dep_graph);

        let stat_dep_graph = resolve_stats(
            stat_specs.iter().map(|s| s.as_str())
                .chain(build_dep_graph.id_map.specs().map(|id| spec_strings[id.index()].as_str())),
        ).await?;

        uninstall_pkgs(&stat_dep_graph, self.recursive, self.force_deployed).await?;

        Ok(())
    }
}
